//
//  EDSVideoCropViewController.m
//  DrivieSchoolStudents
//
//  Created by TangBin on 2019/5/27.
//  Copyright © 2019 班文政. All rights reserved.
//

#import "EDSVideoCropViewController.h"
#import <AVFoundation/AVFoundation.h>
#import "EDSVideoPreviewBottomView.h"
#import "EDSVideoCropView.h"
#import "DoImagePickerManager.h"

@interface EDSVideoCropViewController () <EDSVideoCropViewDelegate>

@property (nonatomic, strong) EDSVideoPreviewBottomView *bottomView;

@property (nonatomic, strong) EDSVideoCropView *cropView;

@property (nonatomic, strong) AVPlayerItem *playerItem;
@property (nonatomic, strong) AVPlayerLayer *playerLayer;
@property (nonatomic, strong) AVPlayer *player;

@property (nonatomic, strong) NSMutableArray *framesArray;

@property (nonatomic, strong) NSTimer           *repeatTimer;   ///< 循环播放计时器

@property (nonatomic, assign) BOOL      isEdited;       ///< YES：编辑完成

- (void)initWithPlayer;

- (void)initWithBottomView;

- (void)initWithCropView;



@end

@implementation EDSVideoCropViewController

- (void)dealloc
{
    NSLog(@"%s", __func__);
}

- (void)initWithVar
{
    [super initWithVar];
    
    // 手机静音时可播放声音
    AVAudioSession *session = [AVAudioSession sharedInstance];
    [session setActive:YES error:nil];
    [[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
    [session setCategory:AVAudioSessionCategoryPlayback error:nil];
}

- (void)initWithNavBar
{
    [super initWithNavBar];
    
}

- (void)initWithSubView
{
    [super initWithSubView];
    
    self.view.backgroundColor = [UIColor blackColor];
    
    [self initWithPlayer];
    
    [self initWithBottomView];
    
    [self initWithCropView];
    
    [self analysisVideoFrames];
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    self.navigationController.navigationBarHidden = YES;
}

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    
    if (self.player)
    {
        // 释放引用
        [ self invalidatePlayer];
    }
    
}

- (void)initWithPlayer
{
    if (!_player)
    {
        self.playerItem = [[AVPlayerItem alloc] initWithURL:self.model.videoOrAudioUrl];
        [self.playerItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
        
        self.player = [AVPlayer playerWithPlayerItem:self.playerItem];
        [self.player addObserver:self forKeyPath:@"timeControlStatus" options:NSKeyValueObservingOptionNew context:nil];
        
        self.playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.player];
        self.playerLayer.videoGravity = AVLayerVideoGravityResizeAspect;
        self.playerLayer.contentsScale = [UIScreen mainScreen].scale;
        self.playerLayer.frame = CGRectMake(0, 0, kScreenWidth, kScreenHeight - 50 - TABBAR_HEIGHT);
        [self.view.layer addSublayer:self.playerLayer];
    }
    
    
    
}

- (void)initWithBottomView
{
    if (!_bottomView)
    {
        CGRect frame = CGRectMake(0, kScreenHeight - TABBAR_HEIGHT, kScreenWidth, TABBAR_HEIGHT);
        _bottomView = [[EDSVideoPreviewBottomView alloc] initWithFrame:frame leftTitle:@"取消" rightTitle:@"完成"];
        [self.view addSubview:_bottomView];
        @weakify(self);
        // 取消按钮事件
        [[_bottomView.btnCrop rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) {
            @strongify(self);
            [self.navigationController popViewControllerAnimated:YES];
        }];
        
        // 完成按钮事件
        [[_bottomView.btnFinished rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) {
            @strongify(self);
            [self cropVideoFinish];
        }];
    }
}

- (void)initWithCropView
{
    if (!_cropView)
    {
        CGRect frame = CGRectMake(0, 0, kScreenWidth, kEDSVideoCropViewHeight);
        _cropView = [[EDSVideoCropView alloc] initWithFrame:frame seconds:self.model.seconds];
        [self.view addSubview:_cropView];
        _cropView.bottom = _bottomView.top;
        _cropView.delegate = self;
    }
}

/**
 释放引用
 */
- (void)invalidatePlayer
{
    [self stopTimer];
    [self.player removeObserver:self forKeyPath:@"timeControlStatus"];
    [self.player pause];
    [self.playerItem removeObserver:self forKeyPath:@"status"];
}

/**
 进行裁剪视频
 */
- (void)cropVideoFinish
{
    [SVProgressHUD showWithStatus:@"正在处理..."];
    NSString *newVideoPath = [[EDSUtility getVideoCachePath] stringByAppendingPathComponent:@"cropvideo123.mp4"];
    NSURL *outputUrl = [NSURL fileURLWithPath:newVideoPath];
    
    [EDSUtility removeWithLocalFile:outputUrl]; // 删除文件
    
    
    AVAsset *asset = [AVAsset assetWithURL:self.model.videoOrAudioUrl];
    
    //    AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:asset presetName:AVAssetExportPresetPassthrough];
    AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:asset presetName:AVAssetExportPresetMediumQuality];
    exportSession.outputURL = outputUrl;
    exportSession.outputFileType = AVFileTypeMPEG4;
    exportSession.shouldOptimizeForNetworkUse = YES;
    
    debugLog(@"startTime=%f; endTime=%f", self.cropView.startTime, self.cropView.endTime);
    CMTime start = CMTimeMakeWithSeconds(self.cropView.startTime, self.player.currentTime.timescale);
    CMTime duration = CMTimeMakeWithSeconds(self.cropView.endTime - self.cropView.startTime, self.player.currentTime.timescale);
    CMTimeRange range = CMTimeRangeMake(start, duration);
    exportSession.timeRange = range;
    @weakify(self);
    [exportSession exportAsynchronouslyWithCompletionHandler:^{
        @strongify(self);
        switch ([exportSession status])
        {
            case AVAssetExportSessionStatusFailed:
            {
                debugLog(@"Export failed: %@", [[exportSession error] localizedDescription]);
                dispatch_async(dispatch_get_main_queue(), ^{
                    [SVProgressHUD showInfoWithStatus:@"处理失败！"];
                });
            } break;
            case AVAssetExportSessionStatusCancelled:
            {
                debugLog(@"Export canceled");
//                [SVProgressHUD dismiss];
                dispatch_async(dispatch_get_main_queue(), ^{
                    [SVProgressHUD showInfoWithStatus:@"处理失败！"];
                });
            } break;
                
            case AVAssetExportSessionStatusCompleted:
            {
                debugLog(@"export completed");
                CGFloat fileSize = [EDSUtility getFileSize:outputUrl.path];
                CGFloat seconds = [EDSUtility getVideoLength:outputUrl];
                debugLog(@"fileSize=%f; second=%f", fileSize, seconds);
                
                self.model.videoOrAudioUrl = outputUrl;
                self.model.fileSize = fileSize;
                self.model.seconds = seconds;
                self.model.type = 1;
                
                // 获取第一帧图片
                UIImage *srcImage = [EDSUtility firstFrameWithVideoURL:outputUrl size:CGSizeZero];
                self.model.srcImage = srcImage;
                
                dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                    [SVProgressHUD dismiss];
                    [[NSNotificationCenter defaultCenter] postNotificationName:kVIDEO_CLIP_FINISHED_NOTI object:self.model];
                });
                
            } break;
                
            default:
                debugLog(@"Export other=%d", (int)[exportSession status]);
                dispatch_async(dispatch_get_main_queue(), ^{
                    [SVProgressHUD showInfoWithStatus:@"处理失败！"];
                });
                break;
        }
    }];
    
    
}

#pragma mark - 定时器相关
- (void)startTimer
{
    //    NSLog(@"endPointX=%.2f; startPointx=%.2f", self.cropView.endTime, self.cropView.startTime);
    double durationTime = self.cropView.endTime - self.cropView.startTime;//(self.cropView.endPointX - self.cropView.startPointX - 20) / kScreenWidth * 10;
    //    NSLog(@"durationTime=%f", durationTime);
    
    [self.cropView startTimer];
    
    // 开启循环播放
    self.repeatTimer = [NSTimer scheduledTimerWithTimeInterval:durationTime target:self selector:@selector(repeatPlay) userInfo:nil repeats:YES];
    [self.repeatTimer fire];
}

- (void)repeatPlay
{
    [self.player play];
    CMTime start = CMTimeMakeWithSeconds(self.cropView.startTime, self.player.currentTime.timescale);
    [self.player seekToTime:start toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero];
}

- (void)stopTimer
{
    [self.repeatTimer invalidate];
    [self.cropView stopTimer];
}

/**
 读取解析视频帧
 */
- (void)analysisVideoFrames
{
    // 初始化asset对象
    AVURLAsset *videoAsset = [[AVURLAsset alloc]initWithURL:self.model.videoOrAudioUrl options:nil];
    // 获取总视频的长度 = 总帧数 / 每秒的帧数
    long videoSumTime = (long)(videoAsset.duration.value / videoAsset.duration.timescale);
    //    NSLog(@"videoSumTime=%ld", videoSumTime);
    // 创建AVAssetImageGenerator对象
    AVAssetImageGenerator *generator = [[AVAssetImageGenerator alloc]initWithAsset:videoAsset];
    generator.maximumSize = CGSizeMake(kScreenWidth, 80);//bottomView.frame.size;
    generator.appliesPreferredTrackTransform = YES;
    generator.requestedTimeToleranceBefore = kCMTimeZero;
    generator.requestedTimeToleranceAfter = kCMTimeZero;
    
    
    // total=180; 60s  10张   60/10=6
    // 180/6=30
    
    // 添加需要帧数的时间集合
    self.framesArray = [NSMutableArray array];
    float step = 0;
    if (videoSumTime > 60)
    {
        step = 4;
    }
    else
    {
        step = videoSumTime / 15.0;
    }
    for (float i = 0; i < videoSumTime; i+=step)
    {
        //        NSLog(@"i=%d", i);
        CMTime time = CMTimeMake(i * videoAsset.duration.timescale , videoAsset.duration.timescale);
        
        //        int second = time.value/time.timescale;
        //        NSLog(@"second = %d", second);
        
        NSValue *value = [NSValue valueWithCMTime:time];
        [self.framesArray addObject:value];
    }
    
    __block long count = 0;
    @weakify(self);
    [generator generateCGImagesAsynchronouslyForTimes:self.framesArray completionHandler:^(CMTime requestedTime, CGImageRef img, CMTime actualTime, AVAssetImageGeneratorResult result, NSError *error){
        @strongify(self);
        if (result == AVAssetImageGeneratorSucceeded)
        {
            //            NSLog(@"%ld",count);
            UIImage *image = [UIImage imageWithCGImage:img];
            [self.cropView addImageFrame:count image:image];
            count++;
        }
        
        if (result == AVAssetImageGeneratorFailed)
        {
            NSLog(@"Failed with error: %@", [error localizedDescription]);
        }
        
        if (result == AVAssetImageGeneratorCancelled)
        {
            NSLog(@"AVAssetImageGeneratorCancelled");
        }
    }];
}

#pragma mark - KVO 属性播放属性监听
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
{
    if ([keyPath isEqualToString:@"status"])
    {
        switch (self.playerItem.status)
        {
            case AVPlayerStatusUnknown:
                NSLog(@"KVO：未知状态，此时不能播放");
                break;
            case AVPlayerStatusReadyToPlay:
                if (!self.player.timeControlStatus || self.player.timeControlStatus != AVPlayerTimeControlStatusPaused)
                {
                    [_player play];
                    if (!self.isEdited)
                    {// 没有编辑完成
                        [self startTimer];
                    }
                }
                NSLog(@"KVO：准备完毕，可以播放");
                break;
            case AVPlayerStatusFailed:
                NSLog(@"KVO：加载失败，网络或者服务器出现问题");
                break;
            default:
                break;
        }
    }
    
    if ([keyPath isEqualToString:@"timeControlStatus"])
    {
        // 剪切完视频后自动循环播放
        if (self.player.timeControlStatus == AVPlayerTimeControlStatusPaused)
        {
            [self.player seekToTime:CMTimeMake(0, 1)];
            [self.player play];
        }
    }
}

#pragma mark - EDSVideoCropViewDelegate
/**
 开始拖拽的时候
 */
- (void)startTimes
{
    [self startTimer];
}

/**
 拖拽结束的时候
 */
- (void)stopTimes
{
    [self stopTimer];
    
    
}

- (CMTimeScale)getCurrentTime
{
    return self.player.currentTime.timescale;
}

- (void)seekTotime:(CMTime)time withBefore:(CMTime)before withAfter:(CMTime)after
{
    [self.player seekToTime:time toleranceBefore:before toleranceAfter:after];
}

@end


























